package com.ibm.spatiotemp.server.datamodel.gpsdata.geoIndexdb;

import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

import org.apache.log4j.Logger;

import com.ibm.spatiotemp.datamodel.datatype.TemporalLineString;
import com.ibm.spatiotemp.datamodel.datatype.TemporalLineString.LineStringComparator;
import com.ibm.spatiotemp.server.config.LocalConfig;
import com.ibm.spatiotemp.server.datamodel.gpsdata.TSPoint;
import com.ibm.spatiotemp.server.datamodel.gpsdata.TSPointResultSet;

/**
 * GeoIndexTSPointResultSet resultset returned from GeoIndexDB, will support
 * Paging & session-timeout via redis-ttl later
 * 
 * @author xuxiaomin
 * 
 */
public class GeoIndexTSPointResultSet extends TSPointResultSet {

	public static Logger logger = Logger
			.getLogger(GeoIndexTSPointResultSet.class);

	/* used to find out paging server(redis server) */
	/* need to auto generated */
	/* currently, paging is not supported */
	private HashMap<String, Vector<TSPoint>> resultMap;

	private Iterator<Map.Entry<String, Vector<TSPoint>>> keyvalueiter;
	private Iterator<TSPoint> vectoriter;

	/**
	 * 
	 * @param ssid
	 * @param starts
	 * @param endts
	 * @param rset
	 */
	public GeoIndexTSPointResultSet(String ssid, long starts, long endts,
			List<TemporalLineString> rset) {
		this.sessionID = ssid;
		resultMap = new HashMap<String, Vector<TSPoint>>();
		init(rset, starts, endts);
	}

	@SuppressWarnings("unchecked")
	private void init(List<TemporalLineString> rset, long starts, long endts) {
		Collections.sort(rset, new LineStringComparator());

		Iterator<TemporalLineString> iter = rset.iterator();
		while (iter.hasNext()) {
			TemporalLineString obj = iter.next();
			String key = "" + obj.ts_id;

			Vector<TSPoint> curvec = null;
			if (resultMap.containsKey(key)) {
				curvec = resultMap.get(key);
			} else {
				curvec = new Vector<TSPoint>();
			}

			{
				if (obj.base_timestamp >= starts && obj.base_timestamp <= endts) {
					curvec.addAll((TemporalLineString2TSPointList(obj, starts,
							endts)));
					resultMap.put(key, curvec);
				}
			}
		}

		if (!resultMap.isEmpty()) {
			keyvalueiter = resultMap.entrySet().iterator();
			vectoriter = keyvalueiter.next().getValue().iterator();
		}

	}

	@Override
	public void close() throws Exception {
	}

	@Override
	public TSPoint getNext() throws Exception {
		if (vectoriter == null)
			return null;

		if (vectoriter.hasNext()) {
			return vectoriter.next();
		} else {
			if (keyvalueiter.hasNext()) {
				vectoriter = keyvalueiter.next().getValue().iterator();
				return vectoriter.next();
			} else
				return null;
		}
	}

	/**
	 * only return the moving objet's ids as result
	 * 
	 * @return moving object ids
	 */
	public Set<String> getAllMovingID() {
		if (resultMap == null)
			return null;
		else
			return resultMap.keySet();
	}

	/**
	 * transform linestring object to a list of TSPoint
	 * 
	 * @param lineobj
	 * @return
	 */
	public static List<TSPoint> TemporalLineString2TSPointList(
			TemporalLineString lineobj) {
		if (lineobj == null) {
			logger.error("empty linestring");
			return null;
		}
		int pointcnt = lineobj.point_cnt;
		if (pointcnt <= 0) {
			logger.error("empty linestring");
			return null;
		}

		LinkedList<TSPoint> tsplist = new LinkedList<TSPoint>();

		String tsid = "" + lineobj.ts_id;/* long tsid to string */
		long startts = lineobj.base_timestamp;

		for (int i = 0; i < pointcnt; i++) {
			long curts = startts + lineobj.timestamp_vector[i];
			tsplist.add(new TSPoint(tsid, lineobj.x_vector[i],
					lineobj.y_vector[i], curts));
		}
		return tsplist;
	}

	public static List<TSPoint> TemporalLineString2TSPointList(
			TemporalLineString lineobj, long starts, long endts) {
		if (lineobj == null) {
			logger.error("empty linestring");
			return null;
		}
		int pointcnt = lineobj.point_cnt;
		if (pointcnt <= 0) {
			logger.error("empty linestring");
			return null;
		}
		LinkedList<TSPoint> tsplist = new LinkedList<TSPoint>();

		String tsid = "" + lineobj.ts_id;/* long tsid to string */
		long startts = lineobj.base_timestamp;

		for (int i = 0; i < pointcnt; i++) {
			long curts = startts + lineobj.timestamp_vector[i];
			{
				if (curts >= startts && curts <= endts) {
					tsplist.add(new TSPoint(tsid, lineobj.x_vector[i],
							lineobj.y_vector[i], curts));
				}
			}
		}
		return tsplist;
	}

}
